package com.meida.module.product.provider.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.meida.common.base.service.BaseProductService;
import com.meida.common.constants.CommonConstants;
import com.meida.common.constants.QueueConstants;
import com.meida.common.enums.OnLineEnum;
import com.meida.common.enums.VerifyStatusEnum;
import com.meida.common.enums.YesNoEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.DateUtils;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.utils.JsonUtils;
import com.meida.module.file.provider.service.SysFileService;
import com.meida.module.product.client.entity.ProdCategory;
import com.meida.module.product.client.entity.ProdProduct;
import com.meida.module.product.client.entity.ProdProductdetails;
import com.meida.module.product.client.entity.ProdSku;
import com.meida.module.product.provider.mapper.ProdProductMapper;
import com.meida.module.product.provider.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 产品 实现类
 *
 * @author flyme
 * @date 2019-07-02
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ProdProductServiceImpl extends BaseServiceImpl<ProdProductMapper, ProdProduct> implements ProdProductService, BaseProductService {

    @Resource
    private ProdProductdetailsService productdetailsService;
    @Resource
    private ProdSkuService skuService;

    @Resource
    private ProdGroupProductService prodGroupProductService;

    @Resource
    private ProdCategoryService categoryService;


    @Resource
    private SysFileService fileService;


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforeListEntityMap(CriteriaQuery<ProdProduct> cq, ProdProduct prodProduct, EntityMap requestMap) {
        cq.select(ProdProduct.class, "productId", "productName", "productNo", "productPrice", "onLineState", "auditState", "recommend", "coverImage", "deliveryTime", "oldPrice", "saleCount");
        return super.beforeListEntityMap(cq, prodProduct, requestMap);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ProdProduct> cq, ProdProduct prodProduct, EntityMap requestMap) {
        //排序字段
        String order = requestMap.get("order", "createTime");
        //排序方式
        String sort = requestMap.get("sort", "desc");
        ProdProduct product = cq.getEntity(ProdProduct.class);
        List<Long> categoryIds = cq.getRequestMap().getListLong("categoryIds");
        cq.select(ProdProduct.class, "productId", "productName", "productNo", "productPrice", "productSeries", "productScore", "oldPrice", "saleCount", "onLineState", "auditState", "recommend", "createTime", "updateTime", "coverImage", "deliveryTime", "categoryName");
        setCollecon(cq);
        cq.likeByField(ProdProduct.class, "productSeries");
        cq.likeByField(ProdProduct.class, "productNo");
        if (FlymeUtils.isEmpty(categoryIds)) {
            cq.eq(ProdProduct.class, "categoryId1");
            cq.eq(ProdProduct.class, "categoryId2");
            cq.eq(ProdProduct.class, "categoryId3");
        } else {
            for (int i = 0; i < categoryIds.size(); i++) {
                Integer n = i + 1;
                cq.eq(ProdProduct.class, "categoryId" + n, categoryIds.get(i));
            }
        }
        cq.eq(ProdProduct.class, "brandId");
        cq.eq(ProdProduct.class, "onLineState");
        cq.eq(ProdProduct.class, "auditState");
        cq.eq(ProdProduct.class, "place");
        if (FlymeUtils.isNotEmpty(product)) {
            String keyword = product.getProductName();
            if (FlymeUtils.isNotEmpty(keyword)) {
                cq.and(e -> e.like(FlymeUtils.isNotEmpty(keyword), "productName", keyword).or().like(FlymeUtils.isNotEmpty(keyword), "categoryName", keyword));
                //记录关键字
                rabbitMqClient.put("keyword", keyword).sendMessage("keyWord");
            }
        }
        cq.orderBy(order, sort);
        return ResultBody.ok();
    }

    @Override
    public void afterPageList(CriteriaQuery<ProdProduct> cq, List<EntityMap> data, ResultBody resultBody) {
        EntityMap map = redisUtils.getConfigMap("GLOBAL_CONFIG");
        resultBody.setExtra(map);
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<ProdProduct> cu, ProdProduct product,EntityMap extra) {
        if (FlymeUtils.isNotEmpty(product)) {
            Long productId = product.getProductId();
            EntityMap result = cu.getRequestMap();
            String productDesc = result.get("productDesc");
            String allSpec = result.get("allSpec");
            String afterService = result.get("afterService");
            String packinglist = result.get("packinglist");
            String productVideo = result.get("productVideo");
            String privateSpec = result.get("privateSpec");
            ProdProductdetails prodProductdetails = Optional.ofNullable(productdetailsService.getById(productId)).orElse(new ProdProductdetails());
            prodProductdetails.setAllSpec(allSpec);
            prodProductdetails.setPackinglist(packinglist);
            prodProductdetails.setPrivateSpec(privateSpec);
            prodProductdetails.setAfterService(afterService);
            prodProductdetails.setProductVideo(productVideo);
            prodProductdetails.setProductDesc(productDesc);
            prodProductdetails.setProductDetailsId(productId);
            productdetailsService.saveOrUpdate(prodProductdetails);
            //保存产品所属店铺分类
            String groupIds = cu.getParams("groupIds");
            if (FlymeUtils.isNotEmpty(groupIds)) {
                prodGroupProductService.delProductGroup(productId);
                prodGroupProductService.setProductGroup(productId, groupIds.split(","));
            }
            if (FlymeUtils.isNotEmpty(product)) {
                //保存sku
                String skus = cu.getParams("skus");
                List<ProdSku> skuList = JsonUtils.toList(skus, ProdSku.class);
                if (FlymeUtils.isNotEmpty(skuList)) {
                    //清空规格
                    skuService.deleteByProductId(productId);
                    for (ProdSku prodSku : skuList) {
                        prodSku.setProductId(productId);
                        if (FlymeUtils.isEmpty(prodSku.getImages())) {
                            prodSku.setImages("[]");
                        }
                        prodSku.setEnable(CommonConstants.ENABLED);
                        prodSku.setSeckillNum(prodSku.getNum());
                        prodSku.setSkuTitle(JsonUtils.getMapValue(prodSku.getOwnSpec()));
                        skuService.saveOrUpdate(prodSku);
                    }
                    Optional<ProdSku> max = skuList.stream().min(Comparator.comparing(ProdSku::getPrice));
                    product.setProductPrice(max.get().getPrice());


                }
            }
        }
        return ResultBody.ok();
    }


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ProdProduct product, EntityMap extra) {
        Long companyId = OpenHelper.getCompanyId();
        Integer onLineState = cs.getInt("onLineState", 0);
        Long categoryId1 = cs.getLong("categoryId1");
        Long categoryId2 = cs.getLong("categoryId2");
        Long categoryId3 = cs.getLong("categoryId3");
        product.setCompanyId(companyId);
        //TODO 暂时用企业ID
        product.setShopId(companyId);
        //上架状态
        product.setOnLineState(onLineState);
        //审批状态
        product.setAuditState(VerifyStatusEnum.NO.getCode());
        product.setDeleted(CommonConstants.LOGIC_NOT_DELETE);
        product.setSaleCount(0);
        product.setProdcutType(0);
        product.setProductScore(new BigDecimal("0"));
        String categoryName = "";
        //解析商品分类
        if (FlymeUtils.isNotEmpty(categoryId1)) {
            ProdCategory category1 = categoryService.getById(categoryId1);
            if (FlymeUtils.isNotEmpty(category1)) {
                categoryName += category1.getCategoryName();
                product.setCategoryId1(categoryId1);
            }
        }
        if (FlymeUtils.isNotEmpty(categoryId2)) {
            ProdCategory category2 = categoryService.getById(categoryId2);
            if (FlymeUtils.isNotEmpty(category2)) {
                categoryName += "-" + category2.getCategoryName();
                product.setCategoryId2(categoryId2);
            }
            product.setCategoryId2(categoryId2);
        }
        if (FlymeUtils.isNotEmpty(categoryId3)) {
            ProdCategory category3 = categoryService.getById(categoryId3);
            if (FlymeUtils.isNotEmpty(category3)) {
                categoryName += "-" + category3.getCategoryName();
                product.setCategoryId3(categoryId3);
            }
            product.setCategoryId3(categoryId3);
        }
        product.setCategoryName(categoryName);
        product.setRecommend(CommonConstants.DISABLED);
        //保存sku
        String skus = cs.getParams("skus");
        List<ProdSku> skuList = JsonUtils.toList(skus, ProdSku.class);
        cs.setExtra("skuList", skuList);
        if (FlymeUtils.isNotEmpty(skuList)) {
            Optional<ProdSku> max = skuList.stream().min(Comparator.comparing(ProdSku::getPrice));
            product.setProductPrice(max.get().getPrice());
        }
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, ProdProduct save, EntityMap extra) {
        Long productId = save.getProductId();
        String allSpec = cs.getParams("allSpec");
        String privateSpec = cs.getParams("privateSpec");
        String packinglist = cs.getParams("packinglist");
        String remark = cs.getParams("remark");
        String productDesc = cs.getParams("productDesc");
        String productVideo = cs.getParams("productVideo");
        String afterService = cs.getParams("afterService");
        ProdProductdetails details = new ProdProductdetails();
        details.setAllSpec(allSpec);
        details.setPackinglist(packinglist);
        details.setProductVideo(productVideo);
        details.setPrivateSpec(privateSpec);
        details.setAfterService(afterService);
        details.setProductDesc(productDesc);
        details.setRemark(remark);
        details.setProductDetailsId(productId);
        productdetailsService.save(details);
        //保存产品所属店铺分类
        String groupIds = cs.getParams("groupIds");
        if (FlymeUtils.isNotEmpty(groupIds)) {
            prodGroupProductService.setProductGroup(productId, groupIds.split(","));
        }
        ProdProduct product = cs.getEntity(ProdProduct.class);
        //保存sku
        List<ProdSku> skuList = cs.getExtra("skuList");
        if (FlymeUtils.isNotEmpty(product)) {
            if (FlymeUtils.isNotEmpty(skuList)) {
                for (ProdSku prodSku : skuList) {
                    prodSku.setEnable(CommonConstants.ENABLED);
                    prodSku.setProductId(productId);
                    prodSku.setSeckillNum(prodSku.getNum());
                    if (FlymeUtils.isEmpty(prodSku.getImages())) {
                        prodSku.setImages("[]");
                    }
                    prodSku.setSkuTitle(JsonUtils.getMapValue(prodSku.getOwnSpec()));
                }
                skuService.saveBatch(skuList);
            }
        }

        return ResultBody.ok("添加成功");
    }


    @Override
    public ResultBody beforeDelete(CriteriaDelete<ProdProduct> cd) {
        Long[] ids = cd.getIds();
        Integer count = (Integer) amqpTemplate.convertSendAndReceive(QueueConstants.QUEUE_ORDER_CHECK, ids);
        cd.setCount(count);
        return super.beforeDelete(cd);
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Long[] ids) {
        productdetailsService.remove(cd);
        skuService.deleteByProductId(ids);
        return super.afterDelete(cd, ids);
    }

    @Override
    public ResultBody setonLineState(Long[] productIds, Integer onlineState) {
        ApiAssert.isNotEmpty("主键不能为空", productIds);
        UpdateWrapper product = new UpdateWrapper();
        product.set("onLineState", onlineState);
        product.set("onlineDate", DateUtils.getDateTime());
        product.in("productId", productIds);
        boolean result = update(product);
        if (result) {
            return ResultBody.ok(OnLineEnum.getValue(onlineState) + "成功", onlineState);
        } else {
            return ResultBody.failed(OnLineEnum.getValue(onlineState) + "失败");
        }
    }


    private void setCollecon(CriteriaQuery<ProdProduct> cq) {
        //是否添加收藏标记
        Long userId = OpenHelper.getUserId();
        if (FlymeUtils.isNotEmpty(userId)) {
            cq.addSelect("(select count(targetId) from sys_collecon sc where sc.targetId=product.productId and targetEntity='ProdProduct' and userId=" + userId + ") colleconTag");
        }
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> listRecommend(int count, boolean collecon) {
        return listShopRecommend(null, count, collecon);
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> listShopRecommend(Long shopId, int count, boolean collecon) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.select(ProdProduct.class, "productId", "productName", "coverImage", "oldPrice", "saleCount", "productPrice", "productScore");
        if (collecon) {
            setCollecon(cq);
        }
        cq.eq("onLineState", OnLineEnum.ON.getCode());
        cq.eq("recommend", YesNoEnum.YES.getCode());
        cq.eq("shopId", shopId);
        cq.orderByDesc("createTime");
        cq.last("limit " + count);
        return selectEntityMap(cq);
    }


    @Override
    public ResultBody setonVisibleConfig(Long[] demandIds, Integer visibleType, String visibleConfig) {
        ApiAssert.isNotEmpty("主键不能为空", demandIds);
        ApiAssert.isNotEmpty("配置不能为空", visibleConfig);
        UpdateWrapper up = new UpdateWrapper();
        up.set("visibleConfig", visibleConfig);
        up.in("productId", demandIds);
        up.set("visibleType", visibleType);
        boolean result = update(up);
        if (result) {
            return ResultBody.msg("更新成功");
        } else {
            return ResultBody.failed("更新失败");
        }
    }


    @Override
    public ResultBody findProductSkus(Long productId) {
        ApiAssert.isNotEmpty("产品ID不能为空", productId);
        ProdProductdetails prodProductdetails = productdetailsService.getById(productId);
        ProdProduct prodProduct = getById(productId);
        ApiAssert.isNotEmpty("产品不存在", prodProductdetails);
        //产品规格
        String json = prodProductdetails.getPrivateSpec();
        EntityMap result = new EntityMap();
        //商品规格
        List<EntityMap> skusList = skuService.selectByProductId(productId);
        for (EntityMap entityMap : skusList) {
            String image = entityMap.get("images");
            if (FlymeUtils.isEmpty(image) || image.length() < 10) {
                image = prodProduct.getCoverImage();
                entityMap.put("images", image);
            }
        }
        List<EntityMap> skuDetails = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(json)) {
            //确保规格顺序
            Map<String, Object> map = JSON.parseObject(json, LinkedHashMap.class, Feature.OrderedField);
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String mapKey = entry.getKey();
                Object mapValue = entry.getValue();
                EntityMap m = new EntityMap();
                m.put("title", mapKey);
                m.put("value", mapValue);
                skuDetails.add(m);
            }
        }
        result.put("skuDetails", skuDetails);
        result.put("skusList", skusList);
        result.put("limitNum", -1);
        return ResultBody.ok(result);
    }

    @Override
    public List<ProdProduct> selectByProductIds(Long[] productIds) {
        ApiAssert.isNotEmpty("产品ID不能为空", productIds);
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.in(true, "productId", productIds);
        return list(cq);
    }

    @Override
    public int countByShopId(Long shopId) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.eq(true, "shopId", shopId);
        return count(cq);
    }

    @Override
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        Long productId = result.getLong("productId");
        Long categoryId1 = result.getLong("categoryId1");
        Long categoryId2 = result.getLong("categoryId2");
        Long categoryId3 = result.getLong("categoryId3");
        String handlerName = cq.getHandlerName();
        List<Long> categoryIds = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(categoryId1)) {
            categoryIds.add(categoryId1);
        }
        if (FlymeUtils.isNotEmpty(categoryId2)) {
            categoryIds.add(categoryId2);
        }
        if (FlymeUtils.isNotEmpty(categoryId3)) {
            categoryIds.add(categoryId3);
        }
        result.put("categoryIds", categoryIds);
        //商品规格
        List<EntityMap> skusList = skuService.selectByProductId(productId);
        if (FlymeUtils.isNotEmpty(skusList)) {
            for (EntityMap entityMap : skusList) {
                Long skuId = entityMap.getLong("skuId");
                String image = entityMap.get("images", result.get("coverImage"));
                List<EntityMap> fileList = fileService.selectFileList(skuId, ProdSku.class);
                entityMap.put("images", image);
                entityMap.put("imageList", fileList);
                entityMap.put("imageIds", new ArrayList<>());
            }
            result.put("sku", skusList.get(0));
        }
        //商品规格
        result.put("skus", skusList);
        String videoUrl = "";
        ProdProductdetails details = productdetailsService.getById(productId);
        if (FlymeUtils.isNotEmpty(details)) {
            //商品详情
            result.put("productDesc", details.getProductDesc());
            result.put("allSpec", details.getAllSpec());
            result.put("productImage", details.getProductImage());
            result.put("productVideo", details.getProductVideo());
            BigDecimal freight = FlymeUtils.getBigDecimal(result.getBigDecimal("freight"), "0");
            if (FlymeUtils.gtzero(freight)) {
                result.put("freightName", "¥" + freight);
            } else {
                result.put("freightName", "包邮");
            }
            result.put("remark", details.getRemark());
            videoUrl = details.getProductVideo();
        }

        //产品图片轮播图
        List<EntityMap> sliderImageList = fileService.selectFileListByFileType(productId, ProdProduct.class, "image");

        //追加视频到第一个位置
        if (FlymeUtils.isNotEmpty(videoUrl) && FlymeUtils.isNotEmpty(handlerName)) {
            EntityMap map = new EntityMap();
            map.put("fileId", "1");
            map.put("uid", "1");
            map.put("name", "file.mp4");
            map.put("url", videoUrl);
            map.put("smallOssPath", videoUrl);
            map.put("ossPath", videoUrl);
            sliderImageList.add(0, map);
        }
        result.put("sliderImageList", sliderImageList);

    }

    @Override
    public int countByCompanyId(Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.eq(true, "companyId", companyId);
        return count(cq);
    }

    /**
     * 统计店铺商品数量
     *
     * @param comapnyId
     * @return
     */
    @Override
    public EntityMap totalProduct(Long comapnyId) {
        CriteriaQuery cq = new CriteriaQuery(ProdProduct.class);
        cq.addSelect("sum( CASE WHEN onLineState = 0 THEN 1 ELSE 0 END ) wsjCount");
        cq.addSelect("sum( CASE WHEN onLineState = 1 THEN 1 ELSE 0 END ) ysjCount");
        cq.addSelect("sum( CASE WHEN onLineState = 2 THEN 1 ELSE 0 END ) yxjCount");
        cq.addSelect("sum( CASE WHEN onLineState = 3 THEN 1 ELSE 0 END ) wgxjCount");
        cq.addSelect("sum(1) totalCount");
        cq.eq("deleted", CommonConstants.DEL_NO);
        return findOne(cq);
    }
}
